<?php
/**
 * <https://y.st./>
 * Copyright © 2019 Alex Yst <mailto:copyright@y.st>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org./licenses/>.
**/

$xhtml = array(
	'<{title}>' => 'Learning Journal',
	'<{subtitle}>' => 'CS 3307: Operating Systems 2',
	'<{copyright year}>' => '2019',
	'takedown' => '2017-11-01',
	'<{body}>' => <<<END
<section id="Unit1">
	<h2>Unit 1</h2>
	<p>
		When I took <a href="https://y.st./en/coursework/CS2301/" title="Operating Systems 1">CS 2301</a>, it seemed the entire focus of the course was on Windows.
		That would have been fine, except we were required to use specific Windows applications to get information that competing products could also tell us, then take screenshots of the specific program we were expected to run.
		I&apos;m not on a Windows system, and had no way to run said software.
		Even though I could still get all the required information using other software, it wasn&apos;t good enough for the assignment because the assignment asked us to use the specific software it wanted us to use.
		It was a major headache to deal with.
		I&apos;m hoping this course doesn&apos;t turn out the same way.
		It seems this course requires access to a Linux system, but provides an option for getting remote access to one using a third party.
		This is what should have been the case for the Windows-based course: an option should have been made available for accessing a remote Windows system.
		But no.
		It was just assumed that all students taking the course were on the Windows operating system, and though I wrote several letters to the professor asking what to do in my situation, I never got a response.
		Anyway, if this course either provides a way to get remote access to each operating system we&apos;ll need to work with or we&apos;re only working with Linux, this course&apos;ll go much smoother for me.
		I&apos;m running Debian locally, so I won&apos;t even need a remote Linux system for much, if anything.
		Part of the reading assignment for the week is a 537-page $a[PDF].
		It&apos;s like whoever set up the reading assignment thinks we&apos;re all just made of time.
		I can&apos;t read all that in one week.
		It&apos;s all about the Linux command line though, which I use on an almost-daily basis, so it should be mostly safe to just reference this document as necessary instead of reading it in its entirety.
		The section of the material on why to use threads was informative.
		Making use of multiple processors is useful, though avoiding {$a['I/O']} blocking <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a> seems even more important.
		I wonder if I can speed up my website-compilation script using threads in this way.
	</p>
	<p>
		Pretty much any semi-advanced machine runs an operating system of some sort.
		My laptop, which I use every day, obviously runs an operating system.
		In my case, it runs Debian 9
		I got my mobile device functioning again a few days ago, that has an operating system as well.
		My mobile runs Replicant 4.2.
		My thermostats look like basic dials, any probably don&apos;t have any computers inside, but more-modern thermostats have operating systems as well.
		My refrigerator, freezer, oven, toaster, and blender are also too basic for an operating system, but my microwave oven might have a simple one, which it likely uses to make the numbers display correctly using seven-segment displays.
		For the past year, while my mobile&apos;s been unable to function, I&apos;ve been using a basic digital camera; normally, I just use the mobile&apos;s built-in camera.
		While this digital camera is incredibly basic, it appears to have an operating system of some sort for sure.
		That operating system allows for configuration of the camera, as well as tracking the date and time.
		I don&apos;t actually own a whole lot of electronics, so my laptop, mobile, camera, and probably microwave oven are the only four operating systems I can think of in my home.
		Outside my home though, I interact with other operating systems, such as the ones run by many cash registers at stores.
		Both of the main grocery stores I frequent use computerised cash registers that very clearly run operating systems.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Arpaci-Dusseau. R., &amp; Arpaci-Dusseau, A. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/">Operating systems - three easy pieces</a>. University of Wisconsin-Madison. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/</code>
		</p>
	</div>
</section>
<section id="Unit2">
	<h2>Unit 2</h2>
	<h3>Operating systems</h3>
	<p>
		I&apos;d hoped to find an article on somewhere interesting we can find operating systems, but given that we&apos;re restricted to using the search features of four specific websites that don&apos;t have advanced search features (and don&apos;t even return decent results), that didn&apos;t happen.
		However, I was able to find a more-mundane article.
		Operating systems such as Linux are available on both servers and desktop machines <a href="https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf">(Gillen &amp; Waldman, 2011)</a>.
	</p>
	<p>
		Linux is available for a large number of processor architectures <a href="https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf">(Gillen &amp; Waldman, 2011)</a>.
		When you can&apos;t find another operating system to run on something, Linux can often be your go-to system.
		That makes it easy to get older, unsupported hardware running.
		I used to have an old $a[PowerPC] machine from Apple.
		Apple no longer supported the thing.
		I wasn&apos;t able to get a modern operating system onto it.
		That is, until I tried Linux.
		I was able to run a modern version of a Linux-based system on the machine, because modern Linux still supports so many processor architectures.
		At the time I had the machine, I initially installed Ubuntu on it.
		I installed Debian on the machine, partly because Debian has support for a lot of the unusual architectures, in addition to the common ones.
		Linux breathed new life into the machine, and made it easy to run modern software on the out-dated machine.
		No system besides Linux provides support for as many architectures as Linux <a href="https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf">(Gillen &amp; Waldman, 2011)</a>.
	</p>
	<p>
		Another way that Linux makes things easy is that it has less potential for vendor lock-in than other systems <a href="https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf">(Gillen &amp; Waldman, 2011)</a>.
		Because of this, users of Linux don&apos;t have to worry that they&apos;re going to end up stuck on a single platform, and have to deal with the garbage the provider of that system is going to throw at them in the future with no hope of escape.
		For example, I remember a time when Canonical started building spyware into Ubuntu, a variant of Linux they produce.
		I wasn&apos;t an Ubuntu user, but if I was, I could have switched to Debian, or Red Hat, or Mint, or any of a multitude of other Linux distributions.
		Canonical had to clean up their act, if I recall, to avoid people flocking away from Ubuntu.
		There was no vendor lock-in to keep users there, so Canonical had to actually provide a quality product.
		Linux distributions have to rely on quality to keep users, because users are free to leave at any time.
		Switching is really easy.
		As the article says, commitment to a platform kind of serves as a bit of vendor lock-in <a href="https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf">(Gillen &amp; Waldman, 2011)</a>.
		If I were to switch to another distribution, I&apos;d no doubt have to change my workflow a bit, and that&apos;s a deterrent.
		But if there was a good reason, I could easily migrate to a different distribution if I had to, as there&apos;s no actual vendor lock-in there.
		Rather, the form of vendor lock-in referred to in this instance is more along the lines of habits of the user, not the threat of not prohibitive difficulties and expenses of migrating away.
	</p>
	<h3>The week&apos;s activities</h3>
	<p>
		Last week, we had an upper bound on how much we could write in our learning journals, which was cumbersome.
		I had to leave out a lot of details I otherwise would have included.
		This week though, we instead have a lower bound, which works much better for my writing style.
		I tend to surpass lower bounds on &quot;write about your weekly activities&quot;-type learning journal assignments without even trying.
		The amount of effort I put in tends to reflect how much I&apos;m allowed to write as well.
		When I have to keep things brief, I condense my work so I can have less to write about, so I won&apos;t have to leave as much out.
		Writing also causes me to think more, so I get much more out of the lesson when I can write extensively about it.
	</p>
	<p>
		My first task for the week was to get my discussion post completed and handed in.
		I try to write up at least one discussion post per day between courses, so I usually get my initial post for one course submitted on day zero and my initial post for the other course submitted on day one.
		In this course, we&apos;re to get a paper on concurrency from one of four websites, then report on it.
		Of the four, only one had a search feature that actually returned any relevant results.
		However, it wouldn&apos;t allow me to access any of the papers without getting past a login wall.
		Seriously?
		What kind of nonsense is that?
		Basically, the site must want to be nosey about who reads what papers, and assumes once you&apos;ve got login credentials, you&apos;ll keep using them instead of bothering to register a new account every time to avoid the noxious tracking.
		Clearly, this site hasn&apos;t seen how I deal with stores that charge higher prices to non-members: I register a new membership card for each and every purchase when I have to use that store for whatever reason to avoid having my purchases chained together, and otherwise mostly avoid that store in favour of others because constantly registering new membership cards is a hassle I&apos;d rather avoid.
		More to the point though, we&apos;re required to cite our sources.
		That means that if I used this source, I&apos;d have to link other students to this noxious site, and they&apos;d need to register accounts in order to see what I was citing.
		Even worse, a permanent link to the noxious site would appear on my own website in my journal within the post here.
		(I archive all the products of my studies.)
		Clearly, the right choice was to pick a different website.
		However, the other three websites had the same noxious policy!
		Fine.
		I&apos;d register, but also add a disclaimer to my post explaining that I do not support the website due to its noxious policy and recommend registering with fake account details.
	</p>
	<p>
		So I wrote up the disclaimer,then tried registering with fake details.
		The registration form on the login wall wasn&apos;t functioning.
		So I tried from the dedicated registration page.
		That worked just fine.
		However, after registering, the site pulled a bait and switch on me.
		Instead of sending me the promised article, it sent me to an advertisement on the website of the author.
		My guess was that the hub site isn&apos;t even storing the articles, and is requiring login credentials in order to provide the relevant $a[URI]s on other websites!
		They think it&apos;s okay to coerce people into registering for their own website for resources hosted by other people.
		The audacity!
		And to make matters worse, it seems their article database isn&apos;t even up-to-date, so they can&apos;t even deliver what they promise.
		I got redirected to the ad likely because the actual article no longer exists and that&apos;s how the author&apos;s site handles <code>404</code>s.
	</p>
	<p>
		At first, I was going to use one of the other websites instead just because of the bait and switch, but as I wrote about it, I realised better what was going on.
		It hadn&apos;t occurred to me previously that the articles aren&apos;t hosted on the noxious hub site.
		But because they&apos;re not, I don&apos;t have to link to the noxious hub site.
		I should find another relevant article, one that&apos;s still available, using this stupid first site.
		I couldn&apos;t find anything that seemed relevant though.
		I tried the other three sites again, and still turned up nothing.
		I ended up settling for something from the first site that wasn&apos;t quite relevant, but I just wrote up my post to reflect that I couldn&apos;t find an exact match for the topic.
		That&apos;s what happens when you limit people to using sources from only a tiny subset of the Web: they&apos;re likely not to find exact match for what they&apos;re looking for.
		Of course now, my disclaimer isn&apos;t at all relevant, so I left it out.
	</p>
	<p>
		With the discussion assignment complete, it was time to turn to the reading assignment.
		We were to read three chapters from one book and two from another.
		The link to the second book returned a <code>404</code> though.
		The textbook&apos;s no longer available.
		Thankfully, the chapter titles for the second book were provided.
		One chapter was on accessing your system.
		I don&apos;t know what that means.
		Don&apos;t we already have access to our systems?
		It probably has to do with accessing remote systems or something.
		I&apos;ve done that before.
		I could do with a refresher, but I can make do without one.
		The second chapter was on accessing files and directories.
		I access files and directories on a daily basis.
		I&apos;ll be just fine without reading about how to do that.
		Typically, I use a graphical file manager, but I also access them on occasion via the command line for various reasons, so even if this is a lesson on how to access files via the command line, I&apos;ve already got it covered.
	</p>
	<p>
		While reading the material this week, the textbook provided examples in C.
		This isn&apos;t the first course to do that.
		I&apos;m kind of wondering if this school even includes C in the curriculum.
		It&apos;s an important language to know.
		If I knew one of the courses I&apos;ll be taking taught C and I knew which course that was, I&apos;d be sure to schedule it for next term.
		So far, I&apos;ve taken courses on Java and Python here.
		I took a course that touched upon several languages slightly but didn&apos;t actually teach them, and one of those languages was Perl.
		I forget the others though.
		And one course kind of taught $a[PHP] a bit, though not enough $a[PHP] to actually do anything interesting with.
		$a[PHP] is my native language though, so it&apos;s not like I don&apos;t already do interesting things in $a[PHP].
	</p>
	<p>
		It&apos;s nice to see the basic principle of how to deal with threading though.
		When I have time between terms, I might try applying the principles to the script that builds my website from source.
		All the pages are cryptographically signed, so when there&apos;s a major change, it can take a long time to build.
		Even when there&apos;s not a huge change though, it can take about half a minute to check for changes in the source.
		It&apos;d be nice to speed it up, and threads might be the way to do that.
		Of particular interest to me is the ability to pass values back out of threads as they terminate.
		That seems like a useful feature for a lot of use cases.
	</p>
	<p>
		Last week, I guessed that locking threads out of execution during critical sections was how to deal with race conditions.
		It looks like I wasn&apos;t far off.
		You can specifically lock competing threads out of the critical section without needing to entirely lock them out of execution.
		It seems this is called mutual exclusion <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-api.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>, which was a term several students had in the discussion forum.
		I assume then that they read ahead in the textbook, as it wasn&apos;t introduced until this week.
		Mutual exclusion is achieved in a pretty ingenious way, too.
		The function call used to acquire the lock simply doesn&apos;t return until the lock has been acquired <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-api.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		However, the signalling between threads seems to have a severe limitation.
		There doesn&apos;t seem to be a way to check to see if a thread has signalled without waiting for said signal.
		That means that when you want to know if a thread has reached a specific point in execution, you&apos;ve got to halt what you&apos;re doing ans wait for it to reach said point <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-api.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		You can&apos;t simply check whether the thread has made it, then conditionally work on something else if it hasn&apos;t.
	</p>
	<p>
		My understanding though is that threads within the same process share the same variable space, at least in the global scope.
		It should be possible to use a global variable as a flag, and conditionally execute that way, using similar mechanics as to how race conditions would typically be introduced accidentally.
		The textbook says not to do this though <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-api.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		It performs poorly and can be buggy at times.
		So how is one supposed to conditionally execute the main code if the work in another thread has been completed and code to get other work done if the work the main code depends on isn&apos;t complete?
		Sleeping the main thread and waiting isn&apos;t always the desired behaviour!
		The textbook makes it out like the only reason to avoid the signals and locks is out of laziness, but this isn&apos;t the concern I have.
		I do my best to keep my code clean and pristine.
		I even use $a[XHTML] on my website instead of messy $a[HTML] for that very purpose, because it forces the code to be well-written and not lazy.
		Questioning this system isn&apos;t an issue of laziness.
		I guess a better way to address my issue is this:
		The textbook says to use the locks and signals even when you think you can get away without doing so, which is all well and good.
		But it&apos;s not getting away with not doing so that concerns me.
		I can imagine cases in which I fear not being able to get away with <strong>*using*</strong> locks and signals!
		Locks and signals seem counterproductive for some use cases.
		Hopefully, we look into this sort of use case later in the term, though I&apos;m doubting that we will.
	</p>
	<p>
		Interestingly, locks are implemented as variables that must be passed into the locking and unlocking functions <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		What this means is that there can be multiple locks, completely unrelated to one another.
		Critical sections don&apos;t have to share a lock, so they can be run concurrently.
		For example, if one critical section works only with the variable <var>\$var0</var> and another works only with the variable <var>\$var1</var>, executing the two concurrently won&apos;t cause problems.
		You can give the two sections separate locks, so one section isn&apos;t waiting for the other to be done with <var>\$var0</var> before it uses <var>\$var1</var>.
	</p>
	<p>
		The textbook went into the history of mutual exclusion, starting with the ability to turn off interrupts <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		When I read that old processors allowed this, I sat there in shock for a couple seconds.
		Being able to do that pretty much voids the entire purpose of interrupts!
		Take, for example, a program that calls the function to turn off interrupts at the beginning of its execution, then turns them back on just before it exits.
		It&apos;s an extreme example for sure, but it certainly get the message across without further explanation: a process can use this option to entirely take over the machine.
		And that&apos;s just the case of deliberate misuse.
		What about bugs?
		Interrupts may get turned off, then never get turned back on.
		Even if the operating system makes sure to turn them back on when a program ends, this still means that a process may accidentally take over the machine.
		A big part of the purpose of interrupts is that a program may not intentionally and willingly give up control often enough, or may even end up in an infinite loop and fail to give up control on its own at all.
		Interrupts are vital for ensuring this sort of issue doesn&apos;t take down the entire machine and require a reboot, resulting in downtime and losing all unsaved progress.
		I get it.
		This was a start.
		But still.
		We&apos;ve come a long way from that these days.
	</p>
	<p>
		In both the previous paragraphs, the textbook mentioned something, then I went off and elaborated on the implications.
		After saying what I needed to, I continued reading only to find the textbook said pretty much the same things I did, though in different words.
		The textbook and I seemed to be on the same page in this chapter.
		For this early mutual exclusion method though, I missed something big: the complete ineffectiveness when it comes to execution on multiple processors.
		When dealing with multiple processors, you can&apos;t exclude other threads by preventing the current thread form giving up control of the one processor it&apos;s running on <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		Lost interrupts from other hardware components, such as {$a['I/O']} completion interrupts <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a> are also an issue I failed to account for.
	</p>
	<p>
		The test-and-set instruction is interesting.
		After the instruction was briefly explained, it was easy to see how it could be used to build better locks.
		This time though, I continued reading before writing about how it was done, so as to not to read about what I&apos;d just written this time.
		The concept is exactly as I thought it&apos;d be.
		The thread is able to check to see if the lock is claimed while claiming the lock, but because the claim on the lock doesn&apos;t have a thread identifier attached, claiming the already-claimed lock has no effect.
		When the thread sees that the lock was already claimed, it ignores the fact that it already claimed it and claims it again, repeatedly, until it sees that it succeeded in claiming the eventually-unclaimed unclaimed lock <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		The book introduces the compare-and-set instruction as being capable of creating locks identical to those created with the set-and-test <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>, which is true, but it can also be used to create locks that keep track of which thread has the lock, for example, by setting the lock to the value of some thread $a[ID], where $a[ID]s cannot equal some value that represents the lock being unclaimed.
		For example, using zero as the lock&apos;s unclaimed state as the textbook does, all other values could represent a specific thread.
		Thread one, thread two, et cetera.
		Is this functionality useful?
		I&apos;m not sure.
		But it&apos;s interesting to note.
		The load-linked and store-conditional seem to pretty much operate on a similar principle.
		This time, you can check the value, then try to set the value, but if another thread has already set the value in the mean time, the set will fail.
		Then you check to see whether the set was a success or failure not by checking the value itself again, as the other thread may have set the same value as this thread tried to set (and it <strong>*would*</strong> be the same value, if using the zero/one lock scheme the book uses as an example), but instead checking the return value of the function that sets the value if it hasn&apos;t changed.
		There are extra steps compared to methods using other primitives, but it works.
	</p>
	<p>
		Using the fetch-and-add primitive for a ticket lock wasn&apos;t something I could figure out on my own.
		When the concept was introduced, I started trying to figure out how to use incrementation and decrementation (fetch-and-add negative one) to keep track of the number of threads waiting on the lock, while somehow using the values returned, which would become useless after the first decrementation ... it didn&apos;t make any sense to me.
		The book&apos;s solution is much more simple though: just use a second counter to keep track of which ticket should now execute, and don&apos;t decrement either value <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		For long-running processes, we can see that this still works despite integer limits due to overflow.
		You need to test to see if your ticket matches the value of the second value, not equal or lesser, so as long as you have fewer threads than there are possible values in your integer size (which should even be the case for an integer size of a single byte in nearly every case), it performs as if there were no integer limit.
		That is, assuming the fetch-and-add operates by the same rules as basic addition.
	</p>
	<p>
		When the book said threads waiting for the lock should yield instead of spinning <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>, it hit me like a tonne of bricks.
		Why didn&apos;t I think of that!?
		I&apos;d forgotten that it was called yielding, but I was still very much aware of the concept.
		I even mentioned it above when I was discussion the problem of turning off interrupts.
		Interrupts exist because programs aren&apos;t always well-programmed, and may misbehave, either intentionally or because of error.
		They don&apos;t always yield periodically like they should.
		Clearly, I had all the parts.
		I knew about yielding from a previous course, and now I knew how a thread could tell if it had the lock.
		But I failed to put the two together.
		At this point though, we&apos;d addressed all the problems I&apos;d had in locking mechanics.
		I figured we had the perfect lock now.
		However, not so much.
		The book brought up the problem of context switching overhead when switching to threads that don&apos;t have the lock, and will thus almost immediately yield <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		Oh.
		Right.
		That issue.
		I hadn&apos;t thought of that.
		The textbook claimed we hadn&apos;t solved the starvation problem with that though <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		As in, threads may never get a chance to enter the critical section, while other threads enter and exit numerous times.
		We fixed that by using the fetch-and-add-based queue though.
		Using such a queue doesn&apos;t require the useless spinning.
		It can be used with yielding just fine.
		Admittedly, there&apos;s still a problem to solve at this point in the book, but thread starvation definitely is not it!
		When you turn work toward one problem, you don&apos;t roll back the solution to the problem prior.
	</p>
	<p>
		The <code>park()</code> and <code>unpark()</code> option <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a> seems easy enough, though you then need a a queue that keeps track of thread $a[ID]s.
		That can no longer be done by the threads simply taking and keeping a ticket number.
	</p>
	<p>
		I don&apos;t feel like I got as much from the chapter on lock-based concurrent data structures as I did the chapter on locks themselves.
		As I read about locks themselves, ideas kept clicking and I kept realising implications of things before I&apos;d even get to the part of the book explaining what I&apos;d just realised.
		With lock-based data structures, I just sort of saw the ideas presented, but they didn&apos;t seem to lead me to coming up with the next idea the way the concepts of locks led me in the learning.
		Scaling concurrent use of locked counters seems like a trade-off between inefficiency and temporary accuracy issues <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		For linked lists, the idea is that only things changing the list need to lock the list, not things performing look-ups.
		Also, sometimes an insertion will fail and you&apos;ll need to try it again, so you need to put the lock around the loop that tries repeatedly, not the inner lines that actually make the attempt, so you don&apos;t lock and unlock in a needlessly repetitious manner <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		For queues, you want separate locks for the enqueue and dequeue operations; the head and tail of the queue can be locked separately without ill effect <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		For hash tables, each of the lists the outer structure contains can have it&apos;s own lock <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		This is because determining which list an item should be in doesn&apos;t modify the structure in any way, so it can be determined before claiming any lock which list to use and thus which lock to claim.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Arpaci-Dusseau, R., &amp; Arpaci-Dusseau, A. (2012). <a href="">Interlude: Thread API</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-api.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, R., &amp; Arpaci-Dusseau, A. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf">Lock-based Concurrent Data Structures</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks-usage.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, R., &amp; Arpaci-Dusseau, A. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf">Locks</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-locks.pdf</code>
		</p>
		<p>
			Gillen, A., &amp; Waldman, B. (2011, June). <a href="https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf">Linux in the Mainstream: Growing Deployment of Business-Critical Workloads</a>. Retrieved from <code>https://static.redhat.com/legacy/f/pdf/IDC_Linux_Mainstream.pdf</code>
		</p>
	</div>
</section>
<section id="Unit3">
	<h2>Unit 3</h2>
	<p>
		The book tells us that using signals from a child thread to a parent thread are inefficient because the parent has to spin while waiting <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-bugs.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		Did we learn <strong>*nothing*</strong> from the section on locks?
		Yield.
		Don&apos;t spin.
		Problem solved.
		Furthermore, don&apos;t even do that.
		Have the parent go to sleep and wait for the child to wake it.
		Even better.
		Both are good solutions that we learned from the section on locks and that apply perfectly here.
		Don&apos;t get me wrong, condition variables seem like a better idea for this purpose, as threads don&apos;t even need to know which other threads they&apos;re waking, but the book&apos;s reasoning as to why we need condition variables is very flawed.
		It&apos;s also interesting to note that all inter-thread communications seem to involve race conditions.
		So locks must always be used when communicating across threads.
		Locks aren&apos;t enough when dealing with producers and consumers using a bounded buffer, though a simple while loop sombined with the locks fixes the issue.
		I also find it incredibly unintuitive, but apparently, signalling only wakes one thread with some thread libraries, not all threads waiting on the signal.
		And of course, you have no way to choose which thread gets woken.
		If you need more control like that, you need individual condition variables for each set of threads you want to be able to wake one of (one condition variable for each thread, in the extreme case).
		I thought that unintuitive behaviour to be a severe flaw in the system, but it turns out so-called &quot;spurious wakeups&quot; (multiple threads waking from a single signal they all wait for), the intuitive behaviour, can be performed using <code>pthread_cond_broadcast()</code> (instead of <code>pthread_cond_signal()</code>) <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-bugs.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
		So you can wake one waiting thread when that&apos;ll save resources without causing problems, but wake them all when you need them all woken.
		Semaphores are interesting, and seem to be interchangeable with locks and condition variables, though I&apos;m not sure if either option has clear advantages over the other.
		Reader-writer locks seem useful at first, though they might not actually be that great.
		They seem vital for speed, as they allow multiple readers at once, except that they&apos;re complex, and actually slow things down compared to basic locks <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-sema.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>, so what&apos;s the point?
		
	</p>
	<p>
		Failure to put locks around critical sections was labelled as &quot;atomicity violations&quot; in the study looked at.
		There was nothing new there though, it was just another look at why we need to lock things.
		Another class of bugs, labelled as &quot;order violations&quot; is fixed with condition variables.
		Circular waits are prevented by introducing a lock-acquisition order.
		Hold-and-wait behaviour is prevented by using another lock to lock out all lock-acquisition, then grabbing all needed locks at once.
		This reduces concurrency though, as locks held keep other threads out of some parts not yet being used.
		You could also instead return failure of lock acquisition and do something else (such as release other locks) instead of waiting for a lock to be released, then try to acquire locks later.
		This is similar to something I expressed a desire for last week, except that I wanted it for use with condition variables.
		We were introduced to the concept of a &quot;livelock&quot; as well.
		A &quot;livelock&quot; technically isn&apos;t a deadlock, but it&apos;s very much a deadlock in the traditional sense of no progress getting made.
		Like a stalemate in chess, things move back and forth in a repeating cycle.
		You can add a random delay to resolve livelocks.
		Also, if there&apos;s no mutual exclusion, there are no deadlocks, but good luck avoiding race conditions without mutual exclusion.
		Sometimes mutual exclusion can be avoided, but requires useful primitives and fancy use of said primitives.
		If you can get control of the scheduler, you can leverage that to schedule threads in such a way to avoid deadlock too.
		Ham-fisted approaches to static scheduling can result in reduced performance, but in return, you get no deadlocks.
		The final option is to allow deadlocks to happen if they are rare, then detect them and take some action to remedy the situation.
		The example given by the book was if you tolerated your $a[OS] freezing once a year and needing to reboot <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-bugs.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>, but needing to reboot the $a[OS] is never acceptable.
		It&apos;s a sign of something very poorly designed in the $a[OS] or a lack of the computer-user&apos;s skill in knowing how to recover without reboot.
		You need to reboot if you&apos;re on a crappy system such as Windows, but that&apos;s because <strong>*it&apos;s a crappy system such as Windows*</strong>.
		Event loops seem useful at first, until you realise that they can&apos;t make use of multiple processors, and nearly every general-purpose computer has more than one.
		They also have to be rewritten as $a[API]s change to avoid $a[API] calls that used to be non-blocking, but now block.
		Aside from that though, they completely eliminate the problem of interrupts causing problems with critical sections.
		There&apos;s no need for locking, as there are no extra threads and thus no race conditions <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-events.pdf">(Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012)</a>.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-bugs.pdf">32: Common Concurrency Problems</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-bugs.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-cv.pdf">30: Condition Variables</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-cv.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-events.pdf">33: Event-based Concurrency (Advanced)</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-events.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/threads-sema.pdf">31: Semaphores</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/threads-sema.pdf</code>
		</p>
	</div>
</section>
<section id="Unit4">
	<h2>Unit 4</h2>
	<p>
		Operating systems are everywhere.
		I don&apos;t have as many in my daily life as most people do though.
		I&apos;ve got my mobile and my laptop, which each have an operating system.
		I think my microwave oven, which I rarely use, contains a rather simple operating system for managing the timer and the display.
		I&apos;ve got a digital camera too, which seems to have a simple operating system for managing settings.
		I stopped using the camera though once my mobile started working again.
		The thing had been pretty much dead for over a year, but I got it working again recently.
		I actually installed a new version of the operating system this week, as within that year of not having a working mobile, the developers of my $a[OS] released at least three new versions of the system.
		One of them was a pretty major upgrade, too.
		Outside my home, I also deal with operating systems.
		The registers at grocery stores often have them, for example.
		There&apos;s also a bottle-return credit kiosk at one of the grocery stores.
		I use it to withdraw funds from my bottle-return account to spend on groceries, but unfortunately, the thing runs Windows.
		This week, it withdrew credit from my account and then crashed for the <strong>*forth*</strong> time on me.
		When that happens, I have to wait until I have time to drop by the bottle-redemption centre and get them to credit the lost amount back to my account.
		Windows causes me nothing but trouble like that.
		If they upgraded to a better system (which is to say, if they installed <strong>*any non-Windows system whatsoever*</strong>), it&apos;s likely stop crashing on me and everyone else.
		I frequently see an &quot;out of order&quot; sign on the machine, telling me it probably just crashed on someone else too.
		I&apos;m not the only one hit by this obnoxious issue.
	</p>
	<p>
		The textbook mentions that Intel uses a proprietary interface called Direct Media Interface to connect their processors to {$a['I/O']} chips (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		That doesn&apos;t sound good.
		Standard interfaces work well and are well-understood, so developers are able to write software that works on them.
		I&apos;ll have to look into this Direct Media Interface later when I get time.
		Unless people have successfully reversed engineered it, it&apos;s likely not compatible with clean operating systems that don&apos;t use proprietary, source-codeless blobs, which would mean that I can&apos;t use computers using this interface with my go-to operating system of choice, Debian.
		That&apos;s something I should be aware of, so I can avoid those machines when I go computer-shopping.
		{$a['I/O']} interrupts aren&apos;t a new concept to me, so I don&apos;t have any comments on them, but it&apos;s worth mentioning them for completeness, as they&apos;re a very important feature of modern hardware and operating systems.
		Direct memory access by specialised hardware was also addressed.
		Abstraction of the storage medium was also covered.
		Abstraction really applies to anything that differs between hardware configurations, such as device access (memory mapping versus commands).
		I also hound it interesting to read that about seventy percent of the Linux kernel&apos;s code is just device drivers that&apos;ll never be used on a given instalation of the system, and that those drivers tend to be the written poorly and are the primary cause of kernel crashes (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		Still, I&apos;d rather have these drivers than not have them.
		I never know what hardware I&apos;ll use next, so I appreciate Debian (my Linux distribution of choice) being able to support a wide variety of hardware choices.
		I get nearly all of my computers second-hand, so it&apos;s not like I can be choosy about which hardware to buy based on a short list of supported components, which would be the alternative.
		The section on the anatomy of a hard disk drive was good review.
		I knew all of that in the past, but I&apos;d forgotten a lot of it.
		I wasn&apos;t aware of track skew (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012) though.
		I also wasn&apos;t aware that the operating system tends to try to schedule the jobs with the fastest seek time first when deciding which to allow to read and write to the disk (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		It makes sense though.
		Each job moves the head and the disks.
		If you get the job that&apos;s closest to where you already are, it might bring you closer to one of the other jobs.
		And even if it doesn&apos;t, it&apos;ll at least keep you from moving further from the close job and having to come back to it from a more-distant point, saving travel time twice.
		Preventing starvation still has to be dealt with though 
		That can be done by handling requests in sweeps, only servicing requests that are ahead of where you are in the current sweep and postponing other requests until the next sweep (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		I&apos;d thought that $a[RAID] was implemented in software; that a computer had multiple disks installed and was configured to use them as a $a[RAID].
		However, it seems $a[RAID] is actually done in hardware (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		I guess that makes it easier if you&apos;ve got money, but for me, it makes setting up a $a[RAID] infeasible.
		I don&apos;t have the funds to go out and buy extra hardware.
		The explanation of why peak output can&apos;t be achieved when mirroring due to needing to skip over blocks read from other disks was something I hadn&apos;t thought about.
		Sequential reading just isn&apos;t sped up by utilising both mirrors because both disks still have to spin over just as many blocks as if only one disk were used (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		I was aware of how higher $a[RAID] levels used parity blocks computed from regular blocks, and that the parity blocks could be used along with the remaining blocks they paritied if one failed to recover the blocks was damaged, but I wasn&apos;t sure how that was done.
		It seems it&apos;s a form of XOR computation.
		Strictly speaking, a true XOR outputs <code>1</code> if <strong>*exactly*</strong> one of the bits fed into it is a <code>1</code>.
		When computing across four blocks, that&apos;s four bits at a time fed in.
		The output from a true XOR is of no use to use here.
		However, there&apos;s a second operation that functions as if the first two bits are XORed together, then the result XORed with the next bit, and so on until all bits are used.
		This process outputs a <code>1</code> if an odd number of bits fed in were <code>1</code>s.
		This is the process used to compute the parity block (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012), and is often <strong>*incorrectly*</strong> referred to as a XOR operation using all the bits involved in the actually multiple XOR operations.
		Using this same false XOR operation, you can compute the value of any missing data block using the remaining data blocks along with the parity block.
		And of course, if it&apos;s the parity that breaks, that could be recomputed in the same way using all the data blocks.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-devices.pdf">36: I/O Devices</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-devices.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-disks.pdf">37: Hard Disk Drives</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-disks.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-raid.pdf">38: Redundant Arrays of Inexpensive Disks (RAIDs)</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-raid.pdf</code>
		</p>
	</div>
</section>
<section id="Unit5">
	<h2>Unit 5</h2>
	<h2>My favourite filesystems</h2>
	<p>
		Personally, my favourite filesystems are $a[ext2] and $a[ext4].
		I&apos;m by no means a filesystem format expert, so I pretty much just stick with the basics.
		$a[ext4] is the default filesystem used by Debian, and it&apos;s always worked very well for me, so I&apos;ve stuck with it.
		$a[ext4] resists fragmentation, unlike Windows-based filesystems.
		As we learned from the reading material this week, it seeks out large, continuous free spaces to put new files, but it also moves files to larger free locations when they exceed the space they have in their current spot, if the files grow (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		It&apos;s also got great character support.
		All characters are allowed in filenames, with the exception of the slash, which is reserved as a path separator, and the null byte.
		When am I ever going to want to use a null byte in a file name!?
		That limitation has no effect on me at all.
		The journaling used by $a[ext4] also makes data far less prone to corruption during power loss, and I sometimes fail to notice my laptop&apos;s battery being nearly dead.
		Oops.
		It&apos;s nice to have this anti-corruption mechanism in place.
	</p>
	<p>
		The $a[ext2] filesystem also has a place in my heart.
		It&apos;s main disadvantage over $a[ext4] is it&apos;s lack of journaling, but that&apos;s also one of it&apos;s strengths.
		Flash drives have their lives shortened with every write, an journaling adds writes.
		That makes a non-journaling filesystem such as $a[ext2] great for $a[USB] flash drives.
		And like $a[ext4], $a[ext2]&apos;s filename character support is awesome.
		Only null bytes and slashes are disallowed.
		Having the same character set on both my hard drive and flash drives is important for when I want to transfer files between the two.
		If I formatted my flash drives as $a[FAT], for example, transferring files onto the flash drive would be a headache, as I&apos;d encounter many files that wouldn&apos;t transfer.
		I&apos;d have to search for the files, rename them, transfer them, and rename them back.
		When I transferred the files from my flash drive back to my hard drive, I&apos;d fined the proper filenames had been lost.
		I&apos;d either need to just deal with it or go through the file tree, find the incorrectly-named files, and fix the filenames.
	</p>
	<p>
		Also of note, both of these filesystems have the advantage of case sensitivity.
		I can count on the files <code>example.txt</code> and <code>EXAMPLE.txt</code> being two separate files.
		This is something Windows-based filesystems can&apos;t boast.
		However, these filesystems also both have the disadvantage of not being compatible with non-Linux computers.
		If I for some reason need to transfer files to or from Windows (a situation that almost never comes up in my life), I need to format one of my $a[USB] drives in some Windows-compatible format.
		I gain Windows compatibility for the drive, but I lose proper filename character support, so on the rare occasion I have to do this, I usually format the drive back to $a[ext2] fairly quickly.
	</p>
	<h2>The week&apos;s activities</h2>
	<p>
		The textbook made the claim that a filename is split into two parts, separated with a full stop, with the second part referring to what type of data is contained within the file (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		The book admitted that what code is used to indicate the file is by convention, and that it might not actually match the content of the file.
		However, having a full stop followed by other characters that indicate the type of file - also known as a file extension - is itself a convention.
		Filenames don&apos;t have multiple parts, and no full stop is necessary in a file name at all.
		A user can name files without extensions, and the operating system is full of files without extensions.
		For example, most executable files, such as those in <code>/usr/bin</code>, have no file extension.
	</p>
	<p>
		File descriptors are odd.
		They&apos;re integers that in the right context represent files you want to access (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		The system seems like the sort of thing you&apos;d want to replace with something more object-oriented.
		Instead of keeping this integer and passing it into functions, you would keep an object and call its methods.
		As odd as file descriptors are though, they&apos;re not altogether a foreign concept to me.
		$a[PHP] has a few different ways to access files, one of which uses file handles in a similar way, if I recall correctly.
		The book said the descriptors are process-specific, which means that they don&apos;t actually mean anything.
		Because they don&apos;t mean anything, I assumed their values would have no significance, or in other words, would be effectively random.
		Then the book showed an example, an the descriptor turned out to be <code>3</code>.
		It asked why it wasn&apos;t the expected value of <code>0</code>.
		I thought to myself that the answer was obvious.
		It just happened that way.
		Next time the value might be <code>9845</code>.
		We can&apos;t expect the file descriptor to be a particular value.
		It turns out I was very wrong.
		The values are sequential and start at zero after all.
		There&apos;s just three open pseudo-files from the beginning: standard input, standard output, and standard error, respectively (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		That seems like it bears significance to the code I submitted last week.
		I used <code>2&gt;</code> to strip out messages to standard error to deal with the permission errors <code>find</code> encountered.
		I knew I was stripping out standard error from the output, but I didn&apos;t know why <code>2</code> was used.
		I think this is why.
		I think perhaps I could have redirected output meant for any file or pseudo-file by knowing the correct file descriptor.
		I think the oddest thing about file descriptors though is their concept of a reference count.
		Each thread forked from another thread that had access to that file descriptor is counted, and any of those threads can attempt to close the file.
		It&apos;s only once all threads have either terminated or tried to close the file that it actually gets closed (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		Why?
		It seems like if you need continued use of that file descriptor, you simple <strong>*wouldn&apos;t close it*</strong>.
		Closing the file descriptor is deliberate.
		You shouldn&apos;t need each and every thread to close the descriptor, as if multiple threads are going to use the file, you&apos;d simply leave the file open, and threads that don&apos;t use the file shouldn&apos;t be closing files they have nothing to do with.
	</p>
	<p>
		I knew that the <code>rmdir</code> command and similar function calls in higher-level programming languages only operate on empty directories, but I thought that that was just a common convention used to prevent mistakes and data loss.
		It turns out it&apos;s very much to prevent mistakes and data loss, but it&apos;s not a convention, but something built into the system&apos;s $a[API] (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		The higher-level implementations are probably just making the system call without further modification, which is why they all seem to behave in this similar manner.
	</p>
	<p>
		Apparently, the $a[FAT] filesystem format is unable to support hard links (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		I knew that the filesystems Microsoft developed were severely flawed, but that&apos;s ridiculous.
		It sounds like $a[NTFS] probably supports hard links though.
		It&apos;s still not a great filesystem, though it certainly is an improvement over $a[FAT].
	</p>
	<p>
		The textbook discussed buffering writes to disk, which at first seemed like nothing new.
		It saves writes, as a single update to the bitmaps can be used for multiple new files, and things of that nature.
		It&apos;s important, but not surprising in any way.
		That is, until the book got to writes cancelling each other out.
		A file may be created, but then deleted before it actually gets written to disk.
		In this case, neither write even needs to happen (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		It&apos;s an easy optimisation to understand, but it&apos;s certainly nothing I would have come up with on my own.
		It was also interesting (and a bit unnerving) to read that older database-management software used to insist on writing directly to disks and avoiding the filesystem itself (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		That seems like a corruption issue just waiting to happen.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-implementation.pdf">40: File System Implementation</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-implementation.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-ffs.pdf">41: Locality and The Fast File System</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-ffs.pdf</code>
		</p>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-intro.pdf">39: Interlude: Files and Directories</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-intro.pdf</code>
		</p>
	</div>
</section>
<section id="Unit6">
	<h2>Unit 6</h2>
	<p>
		The learning journal assignment this week doesn&apos;t make any sense.
		We&apos;re asked to discuss a recent time in which encryption would have helped prevent data loss.
		Encryption prevents unauthorised viewing of data, but it doesn&apos;t in any way prevent data from being lost or destroyed.
		Encrypted data isn&apos;t invulnerable, and can still be damaged as easily as unencrypted data.
		The closest thing encryption can do is help detect when data is damaged, but it doesn&apos;t prevent the damage, an has no effect on data that is outright lost (as lost data is seen without encryption).
		Our textbook covers checksums, which are a common method of using hashing to detect when data is damaged (Arpaci-Dusseau &amp; Arpaci-Dusseau, 2012).
		Detecting the damaged data doesn&apos;t prevent it from having been damaged to begin with though.
	</p>
	<p>
		Hashing is subset of encryption; specifically, it&apos;s irreversible encryption.
		It&apos;s useful for generating checksums because hashes are short (you don&apos;t have to store a full second copy of the data) and the same input to a hashing function will always generate the same output.
		Multiple inputs generate the same output, but the chances of a hash collision like that are small.
		If a hash generated from the data you have now doesn&apos;t match the hash you have from the data before, you know that either the data or the hash has changed.
		If the data wasn&apos;t supposed to change, that means one of the two have been corrupted.
		The assumption is that the data was corrupted, but hashes are data too and can be corrupted as well.
		In any case, you&apos;re able to detect the problem and if your data was copied from elsewhere or if you have a backup, you can copy your data from there.
		It&apos;s not the hash that prevents the data loss though, it&apos;s your backup copy.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Arpaci-Dusseau, A., &amp; Arpaci-Dusseau, R. (2012). <a href="http://pages.cs.wisc.edu/~remzi/OSTEP/file-integrity.pdf">45: Data Integrity and Protection</a>. Retrieved from <code>http://pages.cs.wisc.edu/~remzi/OSTEP/file-integrity.pdf</code>
		</p>
	</div>
</section>
<section id="Unit7">
	<h2>Unit 7</h2>
	<p>
		I couldn&apos;t get the chapter hosted on Dropbox to display.
		I wasn&apos;t even sure I&apos;d found the right file, as the reading assignment didn&apos;t point to a file, but instead to someone&apos;s entire directory of stuff.
		I think the correct file was actually in subdirectory too, making it harder to find.
		Once I did find it, it wouldn&apos;t render as an actual page.
		Instead, I was presented with a page of markup.
		I think that was the right file though, as it had a title similar to what we were told to read.
		Another thing we were supposed to read was a $a[PDF] about SELinux that was supposedly hosted on the university&apos;s own server.
		However, that file was actually missing.
		When I tried to access it, I was told there was some error about the data not existing in one of the tables.
		It&apos;s not the first time I&apos;ve encountered this error message when trying to access a document supposedly hosted by the school, and it leads me to believe that the school stores a lot of its documents in a relational database of something.
		Whatever row held that document was probably deleted, and the reading assignment was never updated to match.
		The remaining part of the reading assignment was hosted on Red Hat&apos;s server, and both remained intact and rendered as one would expect.
		It was a textbook chapter on SELinux.
		It was all familiar, and I&apos;m pretty sure I&apos;ve studied this in another course.
		It was excellent review though.
		I&apos;d forgotten exactly what SELinux was, but now I remember.
		It&apos;s the access-control feature that allows specific applications to be authorised or unauthorised to perform actions (Jahoda, Ančincová, Gkioka, &amp; Čapek, n.d.).
		It complements the file permission feature, which instead operates on users.
		While file permissions provide a good start, SELinux provides further tools to make sure software isn&apos;t accessing or modifying something it shouldn&apos;t.
	</p>
	<p>
		So what tools do I use to secure my files?
		Nothing fancy, to be honest.
		To protect the data of the files, I back them up to an external hard drive.
		If something happens to my laptop&apos;s hard drive, I have a backup copy.
		To prevent unauthorised access to my files, I have my hard drive encrypted using $a[LUKS].
		My <code>/boot</code> partition has to remain unencrypted to allow the machine to boot without any external media, but if someone stole my laptop, there&apos;s nothing on that partition that I&apos;d care if they saw.
		It has enough information to tell a thief that the machine runs Debian, and might even tell them it&apos;s specifically Debian 9, but that information isn&apos;t very personal or private.
		Perhaps there&apos;s something else I should be using too, but for now, this security model hasn&apos;t let me down.
	</p>
	<div class="APA_references">
		<h3>References:</h3>
		<p>
			Jahoda, M., Ančincová, B., Gkioka, I., &amp; Čapek, T. (n.d.). <a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/part_i-selinux">Part I. SELinux</a>. Retrieved from <code>https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/part_i-selinux</code>
		</p>
	</div>
</section>
END
);
